package com.msh.starter.captcha.bean;

import com.msh.starter.captcha.third.AnimationEncoder;
import com.msh.starter.captcha.util.CaptchaUtil;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.OutputStream;

public class DynamicImageCaptcha extends AbstractCaptcha{

  public DynamicImageCaptcha(Font font, int width, int height) {
    super(font, width, height);
  }

  @Override
  public void outputStream(String text, OutputStream os) {
    char[] codes = text.toCharArray();
    int length = text.length();
    Color[] colors = CaptchaUtil.colors(length);
    // 随机生成贝塞尔曲线参数
    int x1 = 5;
    int y1 = CaptchaUtil.nextInt(5, height / 2);
    int x2 = width - 5;
    int y2 = CaptchaUtil.nextInt(height / 2, height - 5);
    int ctrlX = CaptchaUtil.nextInt(width / 4, width / 4 * 3);
    int ctrlY = CaptchaUtil.nextInt(5, height - 5);
    if (CaptchaUtil.nextInt(2) == 0) {
      int ty = y1;
      y1 = y2;
      y2 = ty;
    }
    int ctrlX1 = CaptchaUtil.nextInt(width / 4, width / 4 * 3), ctrlY1 = CaptchaUtil.nextInt(5, height - 5);
    int[][] bezier = new int[][]{{x1, y1}, {ctrlX, ctrlY}, {ctrlX1, ctrlY1}, {x2, y2}};
    AnimationEncoder animation = new AnimationEncoder();
    animation.setQuality(180);
    animation.setDelay(100);
    animation.setRepeat(0);
    animation.start(os);
    for (int i = 0; i < length; i++) {
      BufferedImage img = drawImage(colors, codes, i, bezier);
      animation.addFrame(img);
      img.flush();
    }
    animation.finish();
  }


  private BufferedImage drawImage(Color[] colors, char[] chars, int index, int[][] bezier) {
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
    Graphics2D g = (Graphics2D) image.getGraphics();
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, width, height);
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f * CaptchaUtil.nextInt(10)));
    drawOval(g);
    drawLine(g);
    g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f * CaptchaUtil.nextInt(10)));
    g.setStroke(new BasicStroke(1.2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
    CubicCurve2D shape = new CubicCurve2D.Double(bezier[0][0], bezier[0][1], bezier[1][0],
        bezier[1][1], bezier[2][0], bezier[2][1], bezier[3][0], bezier[3][1]);
    g.draw(shape);

    g.setFont(font);
    FontMetrics fontMetrics = g.getFontMetrics();
    int averageWidth = width/chars.length;
    for (int i = 0; i < chars.length; i++) {
      Rectangle2D rectangle2D = fontMetrics.getStringBounds(String.valueOf(chars[i]), g);
      AlphaComposite alpha = AlphaComposite
          .getInstance(AlphaComposite.SRC_OVER, getAlpha(index, i, colors.length));
      g.setComposite(alpha);
      g.setColor(colors[i]);
      g.drawString(String.valueOf(chars[i]), getDrawStringX(rectangle2D, averageWidth, i), getDrawStringY(rectangle2D));
    }
    g.dispose();
    return image;
  }



  private float getAlpha(int i, int j, int length) {
    int num = i + j;
    float r = (float) 1 / (length - 1);
    float s = length * r;
    return num >= length ? (num * r - s) : num * r;
  }

}
